package com.zshan.clinic.admin.service.stock;

import com.zshan.clinic.admin.constant.Constants;
import com.zshan.clinic.admin.entity.dto.StockOrderPurchaseDTO;
import com.zshan.clinic.admin.entity.medical.stock.DrugOut;
import com.zshan.clinic.admin.entity.medical.stock.StockDrugResult;
import com.zshan.clinic.admin.entity.medical.stock.StockOutDTO;
import com.zshan.clinic.admin.entity.vo.StockDrugDetailVo;
import com.zshan.clinic.admin.entity.vo.StockDrugTransVo;
import com.zshan.clinic.admin.entity.vo.StockWarningVo;
import com.zshan.clinic.admin.mapper.stock.SpecStockDrugMapper;
import com.zshan.clinic.admin.service.notice.ClinicNoticeService;
import com.zshan.clinic.common.constant.CommonConstant;
import com.zshan.clinic.common.enums.DrugChangeTypeEnum;
import com.zshan.clinic.common.enums.DrugTransTypeEnum;
import com.zshan.clinic.common.enums.YesOrNoEnum;
import com.zshan.clinic.common.exception.BusinessFailException;
import com.zshan.clinic.common.util.page.PageInfo;
import com.zshan.clinic.common.util.page.PageUtils;
import com.zshan.clinic.common.util.string.StringUtil;
import com.zshan.clinic.common.util.uuid.IdBuilder;
import com.zshan.clinic.database.dao.StockDrugDetailMapper;
import com.zshan.clinic.database.dao.StockDrugMapper;
import com.zshan.clinic.database.dao.StockDrugTransMapper;
import com.zshan.clinic.database.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 库存
 */
@Slf4j
@Service
public class StockDrugService {

    @Autowired
    private StockDrugMapper stockDrugMapper;

    @Autowired
    private StockDrugDetailMapper stockDrugDetailMapper;

    @Autowired
    private StockDrugTransMapper stockDrugTransMapper;

    @Autowired
    private SpecStockDrugMapper specStockDrugMapper;

    @Autowired
    private ClinicNoticeService noticeService;

    /**
     * 药品变动流水
     * @param clinicId
     * @param drugId
     * @param storageId
     * @param pageNo
     * @param pageSize
     * @return
     */
    public PageInfo<StockDrugTransVo> getStockDrugTransList(Long clinicId, Long drugId, Long storageId, Integer pageNo, Integer pageSize) {
        Long totalCount = specStockDrugMapper.getStockDrugTransCount(clinicId,drugId,storageId);
        if(StringUtil.isBlank(totalCount)){
            return PageInfo.build();
        }
        List<StockDrugTransVo> transList = specStockDrugMapper.getStockDrugTransList(clinicId,drugId,storageId,PageUtils.getOffset(pageNo,pageSize),pageSize);
        return new PageInfo<>(totalCount,transList);
    }
    /**
     * 查询库存明细
     * @param clinicId
     * @param drugId
     * @param storageId
     * @param pageNo
     * @param pageSize
     * @return
     */
    public PageInfo<StockDrugDetailVo> getStockDrugDetailList(Long clinicId,Long drugId,Long storageId,Integer pageNo,Integer pageSize){
        Long totalCount = specStockDrugMapper.getStockDrugDetailCount(clinicId,drugId,storageId);
        if(StringUtil.isBlank(totalCount)){
            return PageInfo.build();
        }
        List<StockDrugDetailVo> detailList = specStockDrugMapper.getStockDrugDetailList(clinicId,drugId,storageId,PageUtils.getOffset(pageNo,pageSize),pageSize);
        return new PageInfo<>(totalCount,detailList);
    }

    /**
     * 校验药库的库存信息
     * @param clinicId
     * @param storageId
     * @return
     */
    public boolean validateStockQty(Long clinicId, Long storageId) {
        StockDrugExample example = new StockDrugExample();
        example.createCriteria()
                .andStockIdEqualTo(storageId)
                .andClinicIdEqualTo(clinicId)
                .andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        List<StockDrug> stockDrugList = stockDrugMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(stockDrugList)) {
            return false;
        }
        return stockDrugList.stream().anyMatch(stockDrug ->
                stockDrug.getMinStockQty() > CommonConstant.DEFAULT_0 || stockDrug.getStockQty() > CommonConstant.DEFAULT_0
        );
    }

    /**
     * 发药成功扣减库存
     * @param stockOutDTO
     */
    @Transactional(rollbackFor = Exception.class)
    public void stockOut(StockOutDTO stockOutDTO) {
        // 需要出库的药品（此时已保证 drugId+storageId 唯一）
        List<DrugOut> drugOutList = stockOutDTO.getDrugOutList();
        if(CollectionUtils.isEmpty(drugOutList)){
            return;
        }
        // 查询主表（含 stockTotalMin / needTotalNin）
        List<StockDrugResult> stockDrugList = specStockDrugMapper.getStockDrugListByDrugOut(drugOutList);
        if (CollectionUtils.isEmpty(stockDrugList)) {
            throw new BusinessFailException("库存不足，无法出库！");
        }
        Map<String, StockDrugResult> stockDrugMap = stockDrugList.stream()
                .collect(Collectors.toMap(
                        r -> r.getDrugId() + "-" + r.getStorageId(),
                        Function.identity()
                ));

        // 子表（批次）明细，要求 SQL 已过滤 is_delete/is_enabled 并按 expiry_date ASC 排序，且只取 >0 的库存
        List<StockDrugDetail> detailList = specStockDrugMapper.getStockDetailListByDrugOut(drugOutList);
        if (CollectionUtils.isEmpty(detailList)) {
            throw new BusinessFailException("库存不足，无法出库！");
        }
        Map<String, List<StockDrugDetail>> stockDrugDetailMap = detailList.stream()
                .collect(Collectors.groupingBy(d -> d.getDrugId() + "-" + d.getStorageId()));
        //生成出库的订单号
        String transOutNo = IdBuilder.getUniqueId(DrugTransTypeEnum.getPrefix(stockOutDTO.getTransType()));
        Date currentTime = new Date();
        LocalDate currentDate = LocalDate.now();

        List<StockDrugTrans> stockDrugTransList = new ArrayList<>();
        List<StockDrugDetail> updateStockDrugDetailList = new ArrayList<>();

        // —— 建议以 stockDrugList 为驱动，但你已保证 drugOut 唯一，这里保留你的外层循环 —— //
        for (DrugOut drugOut : drugOutList) {
            final String key = drugOut.getDrugId() + "-" + drugOut.getStorageId();

            // 0) 取 pack 并校验
            Integer pack = drugOut.getMinPackQty();
            if (pack == null || pack <= 0) {
                throw new BusinessFailException("药品[" + drugOut.getDrugName() + "]包装系数(minPackQty)无效！");
            }
            // 1) 扣主表
            StockDrugResult stockDrugResult = stockDrugMap.get(key);
            if (stockDrugResult == null) {
                throw new BusinessFailException("药品[" + drugOut.getDrugName() + "]主库存不存在，无法出库！");
            }
            int stockTotalMin = stockDrugResult.getStockTotalMin();
            int needTotalNin  = stockDrugResult.getNeedTotalNin();
            if (needTotalNin > stockTotalMin) {
                throw new BusinessFailException(drugOut.getDrugName() + "库存不足，无法出库！");
            }
            int remain = stockTotalMin - needTotalNin;
            stockDrugResult.setStockQty(remain / pack);
            stockDrugResult.setMinStockQty(remain % pack);
            stockDrugResult.setUpdateTime(currentTime);

            // 2) 扣子表（FEFO）
            List<StockDrugDetail> stockDrugDetailList = stockDrugDetailMap.get(key);
            if (CollectionUtils.isEmpty(stockDrugDetailList)) {
                throw new BusinessFailException("药品[" + drugOut.getDrugName() + "]无可用批次库存！");
            }
            // 若不完全确信 SQL 已按有效期升序，这里再兜一层（可选）：
            // stockDrugDetailList.sort(Comparator.comparing(StockDrugDetail::getExpiryDate, Comparator.nullsLast(Comparator.naturalOrder())));

            int needLeft = needTotalNin;
            for (StockDrugDetail stockDrugDetail : stockDrugDetailList) {
                if (needLeft <= 0) {
                    break;
                }
                //拆成小单位
                int detailTotal = (stockDrugDetail.getStockQty() * pack) + stockDrugDetail.getMinStockQty();
                if (detailTotal <= 0) {
                    continue;
                }
                int deduct = Math.min(needLeft, detailTotal);
                needLeft -= deduct;

                int detailRemain = detailTotal - deduct;
                stockDrugDetail.setStockQty(detailRemain / pack);
                stockDrugDetail.setMinStockQty(detailRemain % pack);
                stockDrugDetail.setUpdateTime(currentTime);
                updateStockDrugDetailList.add(stockDrugDetail);

                // 流水
                StockDrugTrans stockDrugOut = buildStockDrugOut(
                        deduct, transOutNo, currentDate, currentTime, stockOutDTO, drugOut, stockDrugDetail);
                stockDrugTransList.add(stockDrugOut);
            }
            // 子表兜底：如果还有剩余，说明主/子表不一致
            if (needLeft > 0) {
                throw new BusinessFailException(stockDrugResult.getDrugName() + "批次库存不足，请检查主/子表一致性！");
            }
        }
        // 3) 批量写库（建议顺序：流水 -> 明细 -> 主表）
        if (!stockDrugTransList.isEmpty()) {
            specStockDrugMapper.addDrugTransBatch(stockDrugTransList);
        }
        if (!updateStockDrugDetailList.isEmpty()) {
            specStockDrugMapper.updateStockDrugDetailBatch(updateStockDrugDetailList);
        }
        if (!stockDrugList.isEmpty()) {
            // ⚠️ 建议此 UPDATE 语句加并发保护（如乐观锁 version 或 WHERE 限制最小单位总数 >= 0）
            specStockDrugMapper.batchUpdateStockDrug(stockDrugList);
        }
    }


    public StockDrugTrans buildStockDrugOut(int deduct,
                                            String transOutNo,
                                            LocalDate currentDate,Date currentTime,
                                            StockOutDTO stockOutDTO,DrugOut drugOut,StockDrugDetail stockDrugDetail) {
        StockDrugTrans stockDrugTrans = new StockDrugTrans();
        stockDrugTrans.setChangeType(DrugChangeTypeEnum.REDUCE.getValue());
        stockDrugTrans.setTransType(stockOutDTO.getTransType());
        stockDrugTrans.setTransNo(transOutNo);
        stockDrugTrans.setTransDate(currentDate);
        stockDrugTrans.setRefId(stockOutDTO.getOrderId());
        stockDrugTrans.setDrugId(drugOut.getDrugId());
        stockDrugTrans.setStorageId(drugOut.getStorageId());
        stockDrugTrans.setBatchNo(stockDrugDetail.getBatchNo());
        stockDrugTrans.setBatchDate(stockDrugDetail.getBatchDate());
        stockDrugTrans.setExpiryDate(stockDrugDetail.getExpiryDate());
        stockDrugTrans.setStockQty(deduct / drugOut.getMinPackQty());
        stockDrugTrans.setStockUnit(stockDrugDetail.getStockUnit());
        stockDrugTrans.setMinStockQty(deduct % drugOut.getMinPackQty());
        stockDrugTrans.setMinStockUnit(stockDrugDetail.getMinStockUnit());
        stockDrugTrans.setTransUserId(stockOutDTO.getOutUserId());
        stockDrugTrans.setTransUserName(stockOutDTO.getOutUserBy());
        stockDrugTrans.setTransTime(currentTime);
        stockDrugTrans.setClinicId(stockDrugDetail.getClinicId());
        stockDrugTrans.setIsEnabled(YesOrNoEnum.YES.getValue());
        stockDrugTrans.setIsDelete(YesOrNoEnum.NO.getValue());
        stockDrugTrans.setCreateUserId(stockOutDTO.getOutUserId());
        stockDrugTrans.setCreateBy(stockOutDTO.getOutUserBy());
        stockDrugTrans.setCreateTime(currentTime);
        return stockDrugTrans;
    }


    /**
     * 药品入库
     * @param orderPurchaseDTO
     */
    @Transactional(rollbackFor = Exception.class)
    public void stockIn(StockOrderPurchaseDTO orderPurchaseDTO) {
        // 生成批次号、入库时间
        String purchaseInNo = IdBuilder.getUniqueId(DrugTransTypeEnum.PURCHASE.getPrefix());
        Date currentTime = new Date();
        LocalDate currentDate = LocalDate.now();
        List<StockDrugTrans> stockDrugTranList = new ArrayList<>();
        List<StockDrugDetail> stockDrugDetailList = new ArrayList<>();
        for (StockOrderPurchaseDetail purchaseDetail : orderPurchaseDTO.getDetailList()) {
            // 1.构造入库记录对象
            StockDrugTrans stockDrugIn = buildStockDrugIn(orderPurchaseDTO, purchaseDetail, purchaseInNo, currentDate, currentTime);
            stockDrugTranList.add(stockDrugIn);
            // 3.构造库存明细记录
            stockDrugDetailList.add(buildStockDrugDetail(stockDrugIn));
        }
        // 4.批量插入入库记录
        specStockDrugMapper.addDrugTransBatch(stockDrugTranList);
        //5.批量保存库存明细
        specStockDrugMapper.addDrugDetailBatch(stockDrugDetailList);
        //6.新增或更新库存总表记录
        for (StockDrugDetail stockDrugDetail : stockDrugDetailList) {
            batchAddStockDrug(stockDrugDetail);
        }
    }

    /**
     * 构建入库记录
     * @param purchaseDTO
     * @param stockOrderPurchaseDetail
     * @param inNo
     * @param inDate
     * @param createTime
     * @return
     */
    public StockDrugTrans buildStockDrugIn(StockOrderPurchaseDTO purchaseDTO, StockOrderPurchaseDetail stockOrderPurchaseDetail, String inNo, LocalDate inDate, Date createTime) {
        StockDrugTrans stockDrugTrans = new StockDrugTrans();
        stockDrugTrans.setChangeType(DrugChangeTypeEnum.ADD.getValue());
        stockDrugTrans.setTransType(DrugTransTypeEnum.PURCHASE.getValue());
        stockDrugTrans.setTransNo(inNo);
        stockDrugTrans.setTransDate(inDate);
        stockDrugTrans.setRefId(purchaseDTO.getOrderId());
        stockDrugTrans.setDrugId(stockOrderPurchaseDetail.getDrugId());
        stockDrugTrans.setStorageId(purchaseDTO.getStorageId());
        stockDrugTrans.setBatchNo(stockOrderPurchaseDetail.getBatchNo());
        stockDrugTrans.setBatchDate(stockOrderPurchaseDetail.getBatchDate());
        stockDrugTrans.setExpiryDate(stockOrderPurchaseDetail.getExpiryDate());
        stockDrugTrans.setStockQty(stockOrderPurchaseDetail.getOrderQty());
        stockDrugTrans.setStockUnit(stockOrderPurchaseDetail.getOrderUnit());
        stockDrugTrans.setMinStockQty(stockOrderPurchaseDetail.getMinOrderQty());
        stockDrugTrans.setMinStockUnit(stockOrderPurchaseDetail.getMinOrderUnit());
        stockDrugTrans.setTransUserId(purchaseDTO.getAuditUserId());
        stockDrugTrans.setTransUserName(purchaseDTO.getAuditUserName());
        stockDrugTrans.setTransTime(createTime);
        stockDrugTrans.setClinicId(purchaseDTO.getClinicId());
        stockDrugTrans.setIsEnabled(YesOrNoEnum.YES.getValue());
        stockDrugTrans.setIsDelete(YesOrNoEnum.NO.getValue());
        stockDrugTrans.setCreateUserId(purchaseDTO.getAuditUserId());
        stockDrugTrans.setCreateBy(purchaseDTO.getAuditUserName());
        stockDrugTrans.setCreateTime(createTime);
        return stockDrugTrans;
    }

    /**
     * 构造库存明细
     * @param drugIn
     * @return
     */
    public StockDrugDetail buildStockDrugDetail(StockDrugTrans drugIn) {
        StockDrugDetail stockDrugDetail = new StockDrugDetail();
        stockDrugDetail.setDrugId(drugIn.getDrugId());
        stockDrugDetail.setStorageId(drugIn.getStorageId());
        stockDrugDetail.setBatchNo(drugIn.getBatchNo());
        stockDrugDetail.setBatchDate(drugIn.getBatchDate());
        stockDrugDetail.setExpiryDate(drugIn.getExpiryDate());
        stockDrugDetail.setStockQty(drugIn.getStockQty());
        stockDrugDetail.setStockUnit(drugIn.getStockUnit());
        stockDrugDetail.setMinStockQty(drugIn.getMinStockQty());
        stockDrugDetail.setMinStockUnit(drugIn.getMinStockUnit());
        stockDrugDetail.setTransNo(drugIn.getTransNo());
        stockDrugDetail.setVersion(CommonConstant.DEFAULT_0);
        stockDrugDetail.setClinicId(drugIn.getClinicId());
        stockDrugDetail.setIsEnabled(YesOrNoEnum.YES.getValue());
        stockDrugDetail.setIsDelete(YesOrNoEnum.NO.getValue());
        stockDrugDetail.setCreateUserId(drugIn.getCreateUserId());
        stockDrugDetail.setCreateBy(drugIn.getCreateBy());
        stockDrugDetail.setCreateTime(drugIn.getCreateTime());
        return stockDrugDetail;
    }

    /**
     * 更新库存
     * @param stockDrugDetail
     */
    @Transactional(rollbackFor = Exception.class)
    public void batchAddStockDrug(StockDrugDetail stockDrugDetail) {
        StockDrug dbStockDrug = getStockDrugByDrugIdAndStorageId(stockDrugDetail.getDrugId(), stockDrugDetail.getStorageId());
        if (dbStockDrug == null) {
            dbStockDrug = new StockDrug();
            BeanUtils.copyProperties(stockDrugDetail,dbStockDrug);
            dbStockDrug.setNearestExpiryDate(stockDrugDetail.getExpiryDate());
            dbStockDrug.setVersion(CommonConstant.DEFAULT_0);
            stockDrugMapper.insertSelective(dbStockDrug);
        } else {
            dbStockDrug.setStockQty(dbStockDrug.getStockQty() + stockDrugDetail.getStockQty());
            if (stockDrugDetail.getExpiryDate().isBefore(dbStockDrug.getNearestExpiryDate())) {
                dbStockDrug.setNearestExpiryDate(stockDrugDetail.getExpiryDate());
            }
            dbStockDrug.setUpdateUserId(stockDrugDetail.getCreateUserId());
            dbStockDrug.setUpdateBy(stockDrugDetail.getCreateBy());
            dbStockDrug.setUpdateTime(stockDrugDetail.getCreateTime());
            updateStockDrugByExample(dbStockDrug);
        }
    }

    /**
     * 更新库存
     * @param stockDrug
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateStockDrugByExample(StockDrug stockDrug){
        StockDrugExample example = new StockDrugExample();
        StockDrugExample.Criteria criteria = example.createCriteria();
        criteria.andStockIdEqualTo(stockDrug.getStockId());
        criteria.andVersionEqualTo(stockDrug.getVersion());
        stockDrug.setVersion(stockDrug.getVersion() + CommonConstant.DEFAULT_1);
        int rows = stockDrugMapper.updateByExampleSelective(stockDrug,example);
        if(rows != CommonConstant.DEFAULT_1){
            throw new BusinessFailException("库存更新失败，请稍后再试！");
        }
    };

    /**
     * 根据药品和药库查询库存信息
     * @param drugId
     * @param storageId
     * @return
     */
    public StockDrug getStockDrugByDrugIdAndStorageId(Long drugId,Long storageId){
        StockDrugExample example = new StockDrugExample();
        StockDrugExample.Criteria criteria = example.createCriteria();
        criteria.andDrugIdEqualTo(drugId);
        criteria.andStorageIdEqualTo(storageId);
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        List<StockDrug> stockDrugList = stockDrugMapper.selectByExample(example);
        return CollectionUtils.isEmpty(stockDrugList) ? null : stockDrugList.get(0);
    }

    /**
     * 根据条件分页查询库存明细列表
     */
    public List<StockDrugDetail> getStockDrugDetailListByParams(Long clinicId, Long drugId, Long storageId, Integer pageNo, Integer pageSize) {
        StockDrugDetailExample example = new StockDrugDetailExample();
        StockDrugDetailExample.Criteria criteria = example.createCriteria();
        if (clinicId != null) {
            criteria.andClinicIdEqualTo(clinicId);
        }
        if (drugId != null) {
            criteria.andDrugIdEqualTo(drugId);
        }
        if (storageId != null) {
            criteria.andStorageIdEqualTo(storageId);
        }
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        example.setOffset(PageUtils.getOffset(pageNo, pageSize));
        example.setLimit(pageSize);
        return stockDrugDetailMapper.selectByExample(example);
    }

    /**
     * 添加库存明细记录
     */
    @Transactional(rollbackFor = Exception.class)
    public void addDetail(StockDrugDetail detail) {
        validateStockDrugDetail(detail);
        detail.setIsDelete(YesOrNoEnum.NO.getValue());
        detail.setIsEnabled(YesOrNoEnum.YES.getValue());
        detail.setCreateTime(new Date());
        stockDrugDetailMapper.insertSelective(detail);
    }

    /**
     * 校验库存明细对象
     */
    public void validateStockDrugDetail(StockDrugDetail detail) {
        if (detail.getDrugId() == null) {
            throw new BusinessFailException("药品ID不能为空");
        }
        if (detail.getStorageId() == null) {
            throw new BusinessFailException("库房ID不能为空");
        }
        // 可添加更多业务字段校验
    }

    /**
     * 根据ID查询库存明细
     */
    public StockDrugDetail getStockDrugDetailById(Long detailId) {
        if (detailId == null) {
            return null;
        }
        StockDrugDetail detail = stockDrugDetailMapper.selectByPrimaryKey(detailId);
        if (detail == null || YesOrNoEnum.YES.getValue().equals(detail.getIsDelete())) {
            return null;
        }
        return detail;
    }

    /**
     * 修改库存明细记录
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateDetail(StockDrugDetail detail) {
        validateStockDrugDetail(detail);
        StockDrugDetail dbDetail = getStockDrugDetailById(detail.getDetailId());
        if (dbDetail == null) {
            throw new BusinessFailException("库存明细记录不存在");
        }
        detail.setUpdateTime(new Date());
        stockDrugDetailMapper.updateByPrimaryKeySelective(detail);
    }

    /**
     * 删除库存明细记录（逻辑删除）
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteDetail(StockDrugDetail detail) {
        StockDrugDetail dbDetail = getStockDrugDetailById(detail.getDetailId());
        if (dbDetail == null) {
            throw new BusinessFailException("库存明细记录不存在");
        }
        dbDetail.setIsDelete(YesOrNoEnum.YES.getValue());
        dbDetail.setUpdateUserId(detail.getUpdateUserId());
        dbDetail.setUpdateBy(detail.getUpdateBy());
        dbDetail.setUpdateTime(new Date());
        stockDrugDetailMapper.updateByPrimaryKeySelective(dbDetail);
    }

    /**
     * 启用库存明细记录
     */
    @Transactional(rollbackFor = Exception.class)
    public void enableDetail(StockDrugDetail detail) {
        StockDrugDetail dbDetail = getStockDrugDetailById(detail.getDetailId());
        if (dbDetail == null) {
            throw new BusinessFailException("库存明细记录不存在");
        }
        if (YesOrNoEnum.YES.getValue().equals(dbDetail.getIsEnabled())) {
            return;
        }
        dbDetail.setIsEnabled(YesOrNoEnum.YES.getValue());
        dbDetail.setUpdateUserId(detail.getUpdateUserId());
        dbDetail.setUpdateBy(detail.getUpdateBy());
        dbDetail.setUpdateTime(new Date());
        stockDrugDetailMapper.updateByPrimaryKeySelective(dbDetail);
    }

    /**
     * 停用库存明细记录
     */
    @Transactional(rollbackFor = Exception.class)
    public void disableDetail(StockDrugDetail detail) {
        StockDrugDetail dbDetail = getStockDrugDetailById(detail.getDetailId());
        if (dbDetail == null) {
            throw new BusinessFailException("库存明细记录不存在");
        }
        if (YesOrNoEnum.NO.getValue().equals(dbDetail.getIsEnabled())) {
            return;
        }
        dbDetail.setIsEnabled(YesOrNoEnum.NO.getValue());
        dbDetail.setUpdateUserId(detail.getUpdateUserId());
        dbDetail.setUpdateBy(detail.getUpdateBy());
        dbDetail.setUpdateTime(new Date());
        stockDrugDetailMapper.updateByPrimaryKeySelective(dbDetail);
    }




    /**
     * 根据条件分页查询药品库存表列表
     * @param clinicId 诊所ID
     * @param drugId 药品ID
     * @param pageNo 页码
     * @param pageSize 每页大小
     * @return
     */
    public List<StockDrug> getStockDrugListByParams(Long clinicId, Long drugId, Integer pageNo, Integer pageSize) {
        StockDrugExample example = new StockDrugExample();
        StockDrugExample.Criteria criteria = example.createCriteria();

        if (clinicId != null) {
            criteria.andClinicIdEqualTo(clinicId);
        }
        if (drugId != null) {
            criteria.andDrugIdEqualTo(drugId);
        }
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());

        example.setOffset(PageUtils.getOffset(pageNo, pageSize));
        example.setLimit(pageSize);

        return stockDrugMapper.selectByExample(example);
    }

    /**
     * 添加药品库存表记录
     * @param stockDrug
     */
    @Transactional(rollbackFor = Exception.class)
    public void addDrug(StockDrug stockDrug) {
        validateStockDrug(stockDrug);
        stockDrug.setIsDelete(YesOrNoEnum.NO.getValue());
        stockDrug.setIsEnabled(YesOrNoEnum.YES.getValue());
        stockDrug.setCreateTime(new Date());
        stockDrugMapper.insertSelective(stockDrug);
    }

    /**
     * 校验药品库存表实体
     * @param stockDrug
     */
    public void validateStockDrug(StockDrug stockDrug) {
        if (stockDrug.getDrugId() == null) {
            throw new BusinessFailException("药品ID不能为空");
        }
        // 你可以根据实际情况加更多校验
    }

    /**
     * 根据ID查询药品库存表记录
     * @param stockId
     * @return
     */
    public StockDrug getStockDrugById(Long stockId) {
        if (stockId == null) {
            return null;
        }
        StockDrug stockDrug = stockDrugMapper.selectByPrimaryKey(stockId);
        if (stockDrug == null || YesOrNoEnum.YES.getValue().equals(stockDrug.getIsDelete())) {
            return null;
        }
        return stockDrug;
    }

    /**
     * 修改药品库存表记录
     * @param stockDrug
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateDrug(StockDrug stockDrug) {
        validateStockDrug(stockDrug);
        StockDrug dbStockDrug = getStockDrugById(stockDrug.getStockId());
        if (dbStockDrug == null) {
            throw new BusinessFailException("药品库存不存在");
        }
        stockDrug.setUpdateTime(new Date());
        stockDrugMapper.updateByPrimaryKeySelective(stockDrug);
    }

    /**
     * 删除药品库存表记录（逻辑删除）
     * @param stockDrug
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteDrug(StockDrug stockDrug) {
        StockDrug dbStockDrug = getStockDrugById(stockDrug.getStockId());
        if (dbStockDrug == null) {
            throw new BusinessFailException("药品库存不存在");
        }
        // TODO: 可以加判断是否允许删除，例如库存是否为空等
        dbStockDrug.setIsDelete(YesOrNoEnum.YES.getValue());
        dbStockDrug.setUpdateUserId(stockDrug.getUpdateUserId());
        dbStockDrug.setUpdateBy(stockDrug.getUpdateBy());
        dbStockDrug.setUpdateTime(new Date());
        stockDrugMapper.updateByPrimaryKeySelective(dbStockDrug);
    }

    /**
     * 启用药品库存记录
     * @param stockDrug
     */
    @Transactional(rollbackFor = Exception.class)
    public void enableDrug(StockDrug stockDrug) {
        StockDrug dbStockDrug = getStockDrugById(stockDrug.getStockId());
        if (dbStockDrug == null) {
            throw new BusinessFailException("药品库存不存在");
        }
        if (YesOrNoEnum.YES.getValue().equals(dbStockDrug.getIsEnabled())) {
            return;
        }
        dbStockDrug.setIsEnabled(YesOrNoEnum.YES.getValue());
        dbStockDrug.setUpdateUserId(stockDrug.getUpdateUserId());
        dbStockDrug.setUpdateBy(stockDrug.getUpdateBy());
        dbStockDrug.setUpdateTime(new Date());
        stockDrugMapper.updateByPrimaryKeySelective(dbStockDrug);
    }

    /**
     * 停用药品库存记录
     * @param stockDrug
     */
    @Transactional(rollbackFor = Exception.class)
    public void disableDrug(StockDrug stockDrug) {
        StockDrug dbStockDrug = getStockDrugById(stockDrug.getStockId());
        if (dbStockDrug == null) {
            throw new BusinessFailException("药品库存不存在");
        }
        if (YesOrNoEnum.NO.getValue().equals(dbStockDrug.getIsEnabled())) {
            return;
        }
        dbStockDrug.setIsEnabled(YesOrNoEnum.NO.getValue());
        dbStockDrug.setUpdateUserId(stockDrug.getUpdateUserId());
        dbStockDrug.setUpdateBy(stockDrug.getUpdateBy());
        dbStockDrug.setUpdateTime(new Date());
        stockDrugMapper.updateByPrimaryKeySelective(dbStockDrug);
    }

    /**
     * 库存不足预警
     */
    public void stockWarning() {
        List<StockWarningVo> stockWarningList = specStockDrugMapper.getStockWarningList();
        if(CollectionUtils.isEmpty(stockWarningList)){
            return;
        }
        for(StockWarningVo stockWarningVo : stockWarningList){
            if(StringUtil.isBlank(stockWarningVo.getManagerId())){
                log.info(">>>>>>>>>>>>>诊所没有配置药库管理员，诊所ID:{}，药库名:{}",stockWarningVo.getClinicId(),stockWarningVo.getStorageName());
                continue;
            }
            ClinicNotice clinicNotice = new ClinicNotice();
            clinicNotice.setEmpId(stockWarningVo.getManagerId());
            clinicNotice.setNoticeName(Constants.NOTICE_NAME_STOCK_WARNING);
            clinicNotice.setNoticeContent(String.format(Constants.NOTICE_CONTENT_STOCK_WARNING,stockWarningVo.getStorageName(),stockWarningVo.getDrugName()));
            clinicNotice.setClinicId(stockWarningVo.getClinicId());
            noticeService.addNotice(clinicNotice);
        }
    }
}
